#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <fcntl.h>
#include <errno.h>


#define AF_COMM  45
#define COMM__MAX 14

// 必须与内核头文件严格一致
struct sockaddr_comm {
    sa_family_t comm_family;   // 字段名必须为comm_family
    char        comm_name[COMM__MAX];
};

static int create_comm_socket(const char *name) {
    int sockfd = socket(AF_COMM, SOCK_DGRAM, 0);
    printf("user:sockfd=%d\n",sockfd);
    if (sockfd < 0) {
        fprintf(stderr, "socket() error: %s\n", strerror(errno));
        return -1;
    }

    // 初始化地址结构
    struct sockaddr_comm addr = {
        .comm_family = AF_COMM,
    };
    strncpy(addr.comm_name, name, sizeof(addr.comm_name) - 1);
    addr.comm_name[sizeof(addr.comm_name) - 1] = '\0'; // 确保终止

    // 绑定地址（必须使用完整结构体长度）
    socklen_t addr_len = sizeof(struct sockaddr_comm);
    if (bind(sockfd, (struct sockaddr*)&addr, addr_len) < 0) {
        fprintf(stderr, "bind error: %s\n", strerror(errno));
        close(sockfd);
        return -1;
    }
    printf("user:bind成功\n");
    // 设置为非阻塞
    int flags = fcntl(sockfd, F_GETFL);
    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
        fprintf(stderr, "fcntl error: %s\n", strerror(errno));
        close(sockfd);
        return -1;
    }
    printf("user:create正确返回\n");
    return sockfd;
}

// int run_process(const char *sock_name) {
//     int sockfd = create_comm_socket(sock_name);
//     if (sockfd < 0) return -1;

//     printf("user:准备发送进程号\n");
//     // 发送进程号
//     char pid_msg[64];
//     int self_pid = getpid();
//     printf("user:发送进程号为pid=%d\n",self_pid);
//     snprintf(pid_msg, sizeof(pid_msg), "PID:%d", self_pid);

//     struct sockaddr_comm dest_addr = {
//         .comm_family = AF_COMM,
//     };
//     if (sendto(sockfd, pid_msg, strlen(pid_msg), 0,
//         (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
//         perror("sendto error");
//     }

//     // 接收循环
//     fd_set read_fds;
//     char buffer[1024];
//     while (1) {
//         printf("user:准备发送进程号\n");
//         // 发送进程号
//         char pid_msg[64];
//         int self_pid = getpid();
//         printf("user:发送进程号为pid=%d\n",self_pid);
//         snprintf(pid_msg, sizeof(pid_msg), "PID:%d", self_pid);
    
//         struct sockaddr_comm dest_addr = {
//             .comm_family = AF_COMM,
//         };
//         if (sendto(sockfd, pid_msg, strlen(pid_msg), 0,
//             (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
//             perror("sendto error");
//         }

//         FD_ZERO(&read_fds);
//         FD_SET(sockfd, &read_fds);
//         struct timeval tv = {.tv_sec = 1, .tv_usec = 0};

//         if (select(sockfd + 1, &read_fds, NULL, NULL, &tv) <= 0)
//         continue;

//         if (FD_ISSET(sockfd, &read_fds)) {
//             ssize_t len = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, NULL, 0);
//             printf("user:接收到len=%d\n",len);
//             if (len > 0) {
//                 buffer[len] = '\0';
//                 int sender_pid;
//                 if (sscanf(buffer, "PID:%d", &sender_pid) == 1 && sender_pid != self_pid) {
//                     printf("[Process %d] Received: %s\n", self_pid, buffer);
//                 }
//             }
//         }
//     }

//     close(sockfd);
//     return 0;
// }

// int main(int argc, char *argv[]) {

//     const char *sock_name = "ventruesock";
//     const int process_num = 3;

//     for (int i = 0; i < process_num; ++i) {
//         pid_t pid = fork();
//         if (pid < 0) {
//             perror("fork failed");
//             exit(EXIT_FAILURE);
//         } else if (pid == 0) { // 子进程
//             printf("Child process %d started\n", getpid());
//             exit(run_process(sock_name) ? EXIT_FAILURE : EXIT_SUCCESS);
//         }
//     }

//     // 父进程等待所有子进程
//     int status;
//     while (wait(&status) > 0);

//     return EXIT_SUCCESS;
        
// }

// 发送进程函数（持续发送）
void sender_process(const char *sock_name) {
    int sockfd = create_comm_socket(sock_name);
    if (sockfd < 0) exit(EXIT_FAILURE);

    struct sockaddr_comm dest_addr = {
        .comm_family = AF_COMM,
    };
    strncpy(dest_addr.comm_name, sock_name, sizeof(dest_addr.comm_name) - 1);
    dest_addr.comm_name[sizeof(dest_addr.comm_name)-1] = '\0';

    while (1) {
        char msg[128];
        snprintf(msg, sizeof(msg), "PID:%d:Hello", getpid());
        if (sendto(sockfd, msg, strlen(msg), 0, 
                  (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
            perror("sendto error");
        }
        sleep(5);  // 每秒发送一次
    }
    close(sockfd);
}

// 接收进程函数（持续接收）
void receiver_process(const char *sock_name) {
    int sockfd = create_comm_socket(sock_name);
    if (sockfd < 0) exit(EXIT_FAILURE);
    printf("user:接收时sockfd=%d\n",sockfd);
    fd_set read_fds;
    char buffer[1024];
    while (1) {
        FD_ZERO(&read_fds);
        FD_SET(sockfd, &read_fds);
        struct timeval tv = {.tv_sec = 1, .tv_usec = 0};

        if (select(sockfd+1, &read_fds, NULL, NULL, &tv) <= 0)
        {
            continue;
        }

        if (FD_ISSET(sockfd, &read_fds)) {
            printf("user:准备接收\n");
            ssize_t len = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, NULL, 0);
            printf("==============user:接收len=%d===============\n",len);
            if (len > 0) {
                buffer[len] = '\0';
                printf("[Receiver %d] Received: %s\n", getpid(), buffer);
            }
        }
    }
    close(sockfd);
}

int main() {
    const char *sock_name = "ventruesock";
    
    // 创建1个发送进程 + 2个接收进程
    for (int i = 0; i < 3; ++i) {
        pid_t pid = fork();
        if (pid < 0) {
            perror("fork failed");
            exit(EXIT_FAILURE);
        } else if (pid == 0) {
            if (i == 0) {  // 第1个子进程：持续发送
                sender_process(sock_name);
            } else {        // 第2、3个子进程：持续接收
                receiver_process(sock_name);
            }
            exit(EXIT_SUCCESS);
        }
    }

    // 父进程等待所有子进程
    int status;
    while (wait(&status) > 0);

    return EXIT_SUCCESS;
}